lib/repo: Immediately error creating bare-user repo on tmpfs
authorColin Walters <walters@verbum.org>
Wed, 5 Jul 2017 14:50:34 +0000 (10:50 -0400)
committerAtomic Bot <atomic-devel@projectatomic.io>
Thu, 6 Jul 2017 14:31:37 +0000 (14:31 +0000)
And in general, if for some reason we can't write `user.` xattrs, provide an
error immediately rather than doing it during a later pull. This way the failure
cause is a lot more obvious.

Related: https://github.com/ostreedev/ostree/issues/991

Closes: #993
Approved by: jlebon

src/libostree/ostree-repo-commit.c
src/libostree/ostree-repo-private.h
src/libostree/ostree-repo.c
tests/installed/itest-bareuser-nouserxattrs.sh [new file with mode: 0755]

index 185ab82f62be13dd23b28916c52e7ece3262bece..baeef3f9b09e3dd8460e8191926893335090ae04 100644 (file)
@@ -82,31 +82,21 @@ create_file_metadata (guint32       uid,
   return ret_metadata;
 }
 
-static gboolean
-write_file_metadata_to_xattr (int fd,
-                              guint32       uid,
-                              guint32       gid,
-                              guint32       mode,
-                              GVariant     *xattrs,
-                              GError       **error)
-{
-  g_autoptr(GVariant) filemeta = NULL;
-  int res;
-
-  filemeta = create_file_metadata (uid, gid, mode, xattrs);
-
-  do
-    res = fsetxattr (fd, "user.ostreemeta",
-                     (char*)g_variant_get_data (filemeta),
-                     g_variant_get_size (filemeta),
-                     0);
-  while (G_UNLIKELY (res == -1 && errno == EINTR));
-  if (G_UNLIKELY (res == -1))
-    {
-      glnx_set_error_from_errno (error);
-      g_prefix_error (error, "Unable to set xattr: ");
-      return FALSE;
-    }
+gboolean
+_ostree_write_bareuser_metadata (int fd,
+                                 guint32       uid,
+                                 guint32       gid,
+                                 guint32       mode,
+                                 GVariant     *xattrs,
+                                 GError       **error)
+{
+  g_autoptr(GVariant) filemeta = create_file_metadata (uid, gid, mode, xattrs);
+
+  if (TEMP_FAILURE_RETRY (fsetxattr (fd, "user.ostreemeta",
+                                     (char*)g_variant_get_data (filemeta),
+                                     g_variant_get_size (filemeta),
+                                     0)) != 0)
+    return glnx_throw_errno_prefix (error, "fsetxattr(user.ostreemeta)");
 
   return TRUE;
 }
@@ -248,7 +238,7 @@ commit_loose_regfile_object (OstreeRepo        *self,
     }
   else if (self->mode == OSTREE_REPO_MODE_BARE_USER)
     {
-      if (!write_file_metadata_to_xattr (tmpf->fd, uid, gid, mode, xattrs, error))
+      if (!_ostree_write_bareuser_metadata (tmpf->fd, uid, gid, mode, xattrs, error))
         return FALSE;
 
       /* Note that previously this path added `| 0755` which made every
index 9e00cf40df4caafb550905cf25c5cb67f041e07d..407e2cb3a6f082356fea688e262e4af4378a028a 100644 (file)
@@ -216,6 +216,14 @@ _ostree_repo_has_loose_object (OstreeRepo           *self,
                                GCancellable         *cancellable,
                                GError             **error);
 
+gboolean
+_ostree_write_bareuser_metadata (int fd,
+                                 guint32       uid,
+                                 guint32       gid,
+                                 guint32       mode,
+                                 GVariant     *xattrs,
+                                 GError       **error);
+
 gboolean
 _ostree_repo_write_directory_meta (OstreeRepo   *self,
                                    GFileInfo    *file_info,
index e29b8fca8e2e365b54fe937e28716048f7f2f54d..815d2d654fa894e0d6e916599e13221b4303de57 100644 (file)
@@ -1752,6 +1752,21 @@ ostree_repo_create (OstreeRepo     *self,
         }
     }
 
+  /* Test that the fs supports user xattrs now, so we get an error early rather
+   * than during an object write later.
+   */
+  if (mode == OSTREE_REPO_MODE_BARE_USER)
+    {
+      g_auto(GLnxTmpfile) tmpf = { 0, };
+
+      if (!glnx_open_tmpfile_linkable_at (dfd, ".", O_RDWR|O_CLOEXEC, &tmpf, error))
+        return FALSE;
+      if (fchmod (tmpf.fd, 0600) < 0)
+        return glnx_throw_errno_prefix (error, "fchmod");
+      if (!_ostree_write_bareuser_metadata (tmpf.fd, 0, 0, 644, NULL, error))
+        return FALSE;
+  }
+
   if (!ostree_repo_open (self, cancellable, error))
     return FALSE;
 
diff --git a/tests/installed/itest-bareuser-nouserxattrs.sh b/tests/installed/itest-bareuser-nouserxattrs.sh
new file mode 100755 (executable)
index 0000000..06d3e10
--- /dev/null
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+# Test that initializing a bare-user repo on tmpfs fails
+# Maybe at some point this will be fixed in the kernel
+# but I doubt it'll be soon
+# https://www.spinics.net/lists/linux-mm/msg109775.html
+
+set -xeuo pipefail
+
+dn=$(dirname $0)
+. ${dn}/libinsttest.sh
+
+test_tmpdir=$(prepare_tmpdir)
+trap _tmpdir_cleanup EXIT
+cd ${test_tmpdir}
+
+mkdir mnt
+mount -t tmpfs tmpfs mnt
+if ostree --repo=mnt/repo init --mode=bare-user 2>err.txt; then
+    umount mnt
+    assert_not_reached "bare-user on tmpfs worked?"
+fi
+umount mnt
+assert_file_has_content err.txt "Operation not supported"